Modern computer architectures comprise multiple processors running multiple threads that may each access common memory spaces. In order to prevent these processors and threads from concurrently accessing and modifying the same data at the same time, some modern architectures, such a PowerPC, provide for placing a reserve on the memory address. A reserve allows a program code to view and update data values without jeopardizing data integrity.
When a reservation is not placed, and two threads each attempt to increment data in the same memory address, both threads may read the data from the address, increment the data, and then attempt to write the modified data back to the memory address. When the second thread reads from the memory address before the first thread has written its modified data back to the memory address, the first thread's modification will be lost because the second thread will overwrite the first thread's modification. Thus, data integrity is jeopardized.
When a reserve is used, both threads may place a reserve on the memory address after reading the data. When the second thread reads from the memory address before the first thread has written its modified data back to the memory address, the second thread's reserve invalidates the first thread's reserve. With its reserve invalidated, the first thread's write will fail, and the first thread may then retry its increment of the memory address. Thus, the increments of both threads will be applied to the data at the memory address because even though the second thread interrupted the first thread's access, the first thread may repeat its access so that both the first and second thread's increments will be applied to the data at the memory address.
A modern processor architecture that uses reserves is the PowerPC architecture. The PowerPC architecture provides an instruction set with the commands “lwarx” and “stwcx.” The lwarx instruction loads data from a memory address and places a reserve on that address. The stwcx instruction stores data to an address only if the reserve placed by the lwarx instruction is still intact. The sequence of loading and then storing data is known as a load-store sequence. In the PowerPC architecture, the load-store sequence may be referred to as a lwarx-stwcx sequence. Using the lwarx-stwcx sequence may ensure that no other processor or thread has modified the data between the time the lwarx instruction is executed and the time the stwcx instruction completes.
In addition, programs using a load-store sequence with a reserve may loop continuously until the data that was loaded and modified is successfully stored. For example, a PowerPC program using a lwarx-stwcx sequence may, when the stwcx instruction fails to store the data, loop back and attempt the lwarx-stwcx sequence again until the stwcx instruction succeeds.
Programs using these commands are typically debugged with the aid of a debugging program to test the program. Debugging programs provide for setting breakpoints within the program to allow the developer to observe the functioning of the program. Breakpoints will stop the execution of a program so that the developer may determine if the program is operating properly. Breakpoints may either be set manually by the developer, or breakpoints may be set automatically by the debugging program.
In order to set a breakpoint with a debugging program, modern debuggers will typically replace a program's instruction with a hardware interrupt or other breakpoint trap to halt the execution of the program and return control to the debugger. However, by changing the execution of the program, there is a risk that a reserve on a memory address will be lost. For example, a PowerPC processor can only place one reserve at a time. Thus, if a program places a reserve with the lwarx instruction and this program is then halted and execution is handed over to a debugger, then the process of halting and handing over execution may lose the reserve placed by the lwarx instruction such that the subsequent stwcx instruction will fail.
The lwarx and stwcx instruction pair enables a program code to view and update data values consistently without jeopardizing data integrity by placing a reservation for a specified memory location at the system bus level when loading data from this memory location by lwarx. Several instructions may follow the lwarx instruction until a conditional store is performed to store the updated data value onto this memory location. The load and store of a single data value is done as an atomic operation (an operation during which a processor can simultaneously read a location and write it in the same bus operation) such that any other store to this memory location on any CPU will make the reservation at this memory location disappear, stwcx will fail to store the updated data, and the update operation will be re-driven by the program code. Any hardware interruption or exception that occurs after the load reservation is set but before the stwcx instruction is executed will also remove the reservation.
Generally, source level debuggers (such as a dbx tool on AIX), operate by allowing the user to step one instruction at a time so that the user may view the register context and any memory update. For example, when performing a step at the lwarx instruction on the dbx tool, using the stepi or nexti subcommand, lwarx is executed, following instructions are processed, and a stop occurs at the instruction following the stwcx instruction. This stop occurs after stwcx because if a failure occurs, it occurs upon re-driving the execution back to the lwarx instruction.
Most debuggers implement stepping instructions by setting up a hardware exception at the end of execution of the instruction being stepped or by placing a breakpoint trap at the start of the next instruction. However, a problem occurs because the hardware prevents the stay of the load reservation placed by the lwarx instruction that was just stepped over. Therefore, the stwcx that follows will always fail, and the dbx user will step indefinitely over the instructions bounded by lwarx and stwcx. Thus, when stepi or nexti subcommand are issued in dbx, the dbx tool recognizes the current instruction as lwarx and places a breakpoint trap at the start of the instruction following stwcx and at the start of the instruction that may be encompassed by the lwarx and stwcx instruction sequence. In this way, dbx avoids stepping into any of the instructions present between the lwarx and stwcx but continues execution and stops outside of the lwarx and stwcx sequence.
A problem remains however, because if the user sets a breakpoint at an instruction in the middle of the lwarx and stwcx code sequence, the dbx tool has no way of detecting this. Thus, when the dbx tool is stopped at this instruction, the stwcx will fail, leaving an indefinite loop until the breakpoint is removed.
As such, a need exists to inform developers when stepping through programs or when setting a breakpoint in a program that the next step or breakpoint may unduly interfere with the program's execution.